home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
TCPCMD.C
< prev
next >
Wrap
Text File
|
1993-08-09
|
6KB
|
260 lines
#include <stdio.h>
#include "global.h"
#include "timer.h"
#include "mbuf.h"
#include "netuser.h"
#include "internet.h"
#include "tcp.h"
#include "cmdparse.h"
#include "commands.h"
/* Close a TCP connection */
static int
dotcpclose(int argc,char **argv,void *p)
{
struct tcb *tcb = (struct tcb *)shtop(argv[1]);
if(close_tcp(tcb) == -1) {
tputs(Notval);
return -1;
}
return 0;
}
/* Set initial round trip time for new connections */
static int
doirtt(int argc,char **argv,void *p)
{
setlong(&Tcp_irtt,"TCP irtt",argc,argv);
if(argc < 2){
struct tcp_rtt *tp;
for(tp = &Tcp_rtt[0]; tp < &Tcp_rtt[RTTCACHE]; tp++) {
if(tp->addr != 0) {
tprintf("%s: srtt %ld mdev %ld\n",
inet_ntoa(tp->addr),tp->srtt,tp->mdev);
}
}
}
return 0;
}
/* Force a retransmission */
static int
dotcpkick(int argc,char **argv,void *p)
{
struct tcb *tcb = (struct tcb *)shtop(argv[1]);
if(kick_tcp(tcb) == -1) {
tputs(Notval);
return 1;
}
return 0;
}
/* Set default maximum segment size */
static int
domss(int argc,char **argv,void *p)
{
return setshort(&Tcp_mss,"TCP MSS",argc,argv);
}
/* Eliminate a TCP connection */
static int
dotcpreset(int argc,char **argv,void *p)
{
struct tcb *tcb = (struct tcb *)shtop(argv[1]);
if(!tcpval(tcb)){
tputs(Notval);
return 1;
}
close_self(tcb,RESET);
return 0;
}
static int
dotcpretry(int argc,char **argv,void *p)
{
return setint(&Tcp_retry,"TCP retry",argc,argv);
}
/* Set smoothed round trip time for specified TCB */
static int
dortt(int argc,char **argv,void *p)
{
struct tcb *tcb = (struct tcb *)shtop(argv[1]);
if(!tcpval(tcb)){
tputs(Notval);
return 1;
}
tcb->srtt = atol(argv[2]);
return 0;
}
/* Display status of TCBs */
static int
dotcpstat(int argc,char **argv,void *p)
{
if(argc < 2) {
/* Dump TCP stats and summary of all TCBs
/* &TCB Rcv-Q Snd-Q Local socket Remote socket State
* 1234 0 0 xxx.xxx.xxx.xxx:xxxxx xxx.xxx.xxx.xxx:xxxxx Established
*/
int i, j;
struct tcb *tcb;
for(j = i = 1; i <= NUMTCPMIB; i++) {
if(Tcp_mib[i].name == NULLCHAR)
continue;
tprintf("(%2u)tcp%-17s%10lu",i,Tcp_mib[i].name,Tcp_mib[i].value.integer);
tputs((j++ % 2) ? " " : "\n");
}
if((j % 2) == 0)
tputs("\n");
tputs("&TCB Rcv-Q Snd-Q Local socket Remote socket State\n");
for(tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next){
tprintf("%lx%6u%6u %-23s",
ptol(tcb),tcb->rcvcnt,tcb->sndcnt,pinet(&tcb->conn.local));
tprintf("%-23s%-s",pinet(&tcb->conn.remote),Tcpstates[tcb->state]);
if(tcb->state == TCP_LISTEN && tcb->flags.clone)
tputs(" (S)");
tputs("\n");
}
} else {
struct tcb *tcb = (struct tcb *)shtop(argv[1]);
if(tcpval(tcb)) {
st_tcp(tcb);
} else {
tputs(Notval);
}
}
return 0;
}
static int
dosyndata(int argc,char **argv,void *p)
{
return setbool(&Tcp_syndata,"TCP syn+data piggybacking",argc,argv);
}
static int
dotcptr(int argc,char **argv,void *p)
{
return setbool(&Tcp_trace,"TCP trace",argc,argv);
}
/* Set default window size */
static int
dowindow(int argc,char **argv,void *p)
{
return setshort(&Tcp_window,"TCP window",argc,argv);
}
/* Dump a TCP control block in detail */
void
st_tcp(struct tcb *tcb)
{
/* Compute total data sent and received; take out SYN and FIN */
int32 sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
int32 recvd = tcb->rcv.nxt - tcb->irs;
if(tcb == NULLTCB)
return;
switch(tcb->state){
case TCP_LISTEN:
case TCP_SYN_SENT: /* Nothing received or acked yet */
sent = recvd = 0;
break;
case TCP_SYN_RECEIVED:
recvd--; /* Got SYN, no data acked yet */
sent = 0;
break;
case TCP_ESTABLISHED: /* Got and sent SYN */
case TCP_FINWAIT1: /* FIN not acked yet */
sent--;
recvd--;
break;
case TCP_FINWAIT2: /* Our SYN and FIN both acked */
sent -= 2;
recvd--;
break;
case TCP_CLOSE_WAIT: /* Got SYN and FIN, our FIN not yet acked */
case TCP_CLOSING:
case TCP_LAST_ACK:
sent--;
recvd -= 2;
break;
case TCP_TIME_WAIT: /* Sent and received SYN/FIN, all acked */
sent -= 2;
recvd -= 2;
break;
}
tprintf("Local %s",pinet(&tcb->conn.local));
tprintf(" Remote %s State: %s\n Init seq Unack Next Resent "
"CWind Thrsh Wind MSS Queue Total\n",
pinet(&tcb->conn.remote),
Tcpstates[tcb->state]);
tprintf("Send:%9lx%9lx%9lx",tcb->iss,tcb->snd.una,tcb->snd.nxt);
tprintf("%7lu%6u%6u",tcb->resent,tcb->cwind,tcb->ssthresh);
tprintf("%6u%5u%6u%11lu\n",tcb->snd.wnd,tcb->mss,tcb->sndcnt,sent);
tprintf("Recv:%9lx%18lx%7lu",tcb->irs,tcb->rcv.nxt,tcb->rerecv);
tprintf("%18u%11u%11lu\n",tcb->rcv.wnd,tcb->rcvcnt,recvd);
if(tcb->backoff > 0)
tprintf("Backoff %u ",tcb->backoff);
if(tcb->flags.retran)
tputs("Retrying ");
tputs("Timer ");
switch(tcb->timer.state){
case TIMER_STOP:
tputs("-");
break;
case TIMER_RUN:
tprintf("%lu",read_timer(&tcb->timer));
break;
case TIMER_EXPIRE:
tputs("E");
break;
}
tprintf("/%lu ms SRTT %ld ms Mean dev %ld ms\n",
dur_timer(&tcb->timer),tcb->srtt,tcb->mdev);
if(tcb->reseq != NULLRESEQ) {
struct reseq *rp;
tputs("Reassembly queue:\n");
for(rp = tcb->reseq; rp != NULLRESEQ; rp = rp->next) {
tprintf(" seq x%lx %u bytes\n",rp->seg.seq,rp->length);
}
}
}
/* TCP subcommand table */
int
dotcp(int argc,char **argv,void *p)
{
struct cmds Tcpcmds[] = {
"close", dotcpclose, 0, 2, "tcp close <tcb>",
"irtt", doirtt, 0, 0, NULLCHAR,
"kick", dotcpkick, 0, 2, "tcp kick <tcb>",
"mss", domss, 0, 0, NULLCHAR,
"reset", dotcpreset, 0, 2, "tcp reset <tcb>",
"retry", dotcpretry, 0, 0, NULLCHAR,
"rtt", dortt, 0, 3, "tcp rtt <tcb> <val>",
"status", dotcpstat, 0, 0, NULLCHAR,
"syndata", dosyndata, 0, 0, NULLCHAR,
"trace", dotcptr, 0, 0, NULLCHAR,
"window", dowindow, 0, 0, NULLCHAR,
NULLCHAR,
};
return subcmd(Tcpcmds,argc,argv,p);
}